package com.lanchetech.service.impl;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import com.alibaba.fastjson.JSONObject;
import com.lanchetech.common.enums.MsgUserRoleEnum;
import com.lanchetech.dao.MsgUserMapper;
import com.lanchetech.dao.UserMapper;
import com.lanchetech.entity.MsgUser;
import com.lanchetech.entity.User;
import com.lanchetech.service.JpushService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

@Service
public class JpushServiceImpl implements JpushService {
    protected static final Logger LOG = LoggerFactory.getLogger(JpushServiceImpl.class);

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    MsgUserMapper msgUserMapper;

    @Autowired
    UserMapper userMapper;

    protected static final String APP_KEY = "9322ee0450e4e45d78cdf984";
    protected static final String MASTER_SECRET = "307fc76ee0a65678cf8bb8c1";

    @Override
    public void sendPushToAll(String message, String title, Map<String, String> extras) {
        Notification notification = buildNotification(message, title, extras);
        PushPayload payload = PushPayload.newBuilder().setNotification(notification).build();

        sendPushMessage(payload);
    }

    @Override
    public void sendPushToPerson(String message, String registerId, String title, Map<String, String> extras) {
        Notification notification = buildNotification(message, title, extras);

        PushPayload payload = PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setNotification(notification)
                .setAudience(Audience.registrationId(registerId))
                .build();
        sendPushMessage(payload);
    }

    @Override
    public void sendPushToPeople(String message, List<String> registerIds, String title, Map<String, String> extras) {
        Notification notification = buildNotification(message, title, extras);

        PushPayload payload = PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setNotification(notification)
                .setAudience(Audience.registrationId(registerIds))
                .build();
        sendPushMessage(payload);
    }

    @Override
    public void sendPushToTags(String message, List<String> tags, String title, Map<String, String> extras) {
        Notification notification = buildNotification(message, title, extras);

        PushPayload payload = PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setNotification(notification)
                .setAudience(Audience.tag(tags))
                .build();
        sendPushMessage(payload);
    }

    @Override
    public void sendPushToAlias(String message, List<String> alias, String title, Map<String, String> extras) {
        Notification notification = buildNotification(message, title, extras);

        PushPayload payload = PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setNotification(notification)
                .setAudience(Audience.alias(alias))
                .build();
        sendPushMessage(payload);
    }

    private Notification buildNotification(String message, String title, Map<String, String> extras) {
        Notification notification = Notification.newBuilder()
                .addPlatformNotification(AndroidNotification.newBuilder()
                        .setAlert(message)
                        .setTitle(title)
                        .addExtras(extras)
                        .build())
                .addPlatformNotification(IosNotification.newBuilder()
                        .setAlert(message)
                        .addExtras(extras)
                        .build())
                .build();
        return notification;
    }

    private void sendPushMessage(PushPayload payload) {
        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);

        try {
            PushResult result = jpushClient.sendPush(payload);
            LOG.info("Got result - " + result);
            System.out.println(result);
            jpushClient.close();
        } catch (APIConnectionException e) {
            LOG.error("Connection error. Should retry later. ", e);
            LOG.error("Sendno: " + payload.getSendno());

        } catch (APIRequestException e) {
            LOG.error("Error response from JPush server. Should review and fix it. ", e);
            LOG.info("HTTP Status: " + e.getStatus());
            LOG.info("Error Code: " + e.getErrorCode());
            LOG.info("Error Message: " + e.getErrorMessage());
            LOG.info("Msg ID: " + e.getMsgId());
            LOG.error("Sendno: " + payload.getSendno());
        }
    }

    @Override
    public void handleMessage(JSONObject req) {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        String key = "MsgRid:" + req.getString("friendId");
        String registerId = operations.get(key);

        // 如果为空，则寻找registerId，并设置到redis中
        if (StringUtils.isEmpty(registerId)) {
            MsgUser msgUser = msgUserMapper.selectByPrimaryKey(req.getLong("friendId"));
            if (MsgUserRoleEnum.USER.getRole().equals(msgUser.getRole())) {
                User user = userMapper.selectByPrimaryKey(msgUser.getRelateId());
                if (!StringUtils.isEmpty(user.getRegisterId())) {
                    registerId = user.getRegisterId();
                    operations.set(key, registerId);
                }
            }
        }

        if (!StringUtils.isEmpty(registerId)) {
            String content = req.getString("content");
            if ("image".equals(req.getString("type"))) {
                content = "图片消息";
            } else if ("voice".equals(req.getString("type"))) {
                content = "语音消息";
            }
            sendPushToPerson(content, registerId, req.getString("nickname"), null);
        }
    }
}
